﻿using AbpDemo.Menus;
using AbpDemo.RoleMenus;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
using AbpDemo.Roles;
using Microsoft.AspNetCore.Mvc.ActionConstraints;
using CSRedis;

namespace AbpDemo.Filters
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
    public class CustomerAuthorizationFilterAttribute : AuthorizeAttribute, IAuthorizationFilter
    {
        private readonly string[] permission;

        public CustomerAuthorizationFilterAttribute(params string[] permission)
        {
            this.permission = permission;
        }

        public async void OnAuthorization(AuthorizationFilterContext context)
        {
            if (context.ActionDescriptor.EndpointMetadata.Any(m => m is IAllowAnonymous))
                return;

            if (!context.HttpContext.User.Identity.IsAuthenticated)
            {
                context.Result = new StatusCodeResult((int)HttpStatusCode.Moved);
            }
            else
            {
                IServiceProvider serviceProvider = context.HttpContext.RequestServices;
                var redisClient = serviceProvider.GetService<CSRedisClient>();
                if(!await redisClient.ExistsAsync("Abp:Token"))
                {
                    context.Result = new ForbidResult();
                }
                //基本权限
                if (context.ActionDescriptor.EndpointMetadata.Any(m => m is CustomerAuthorizationFilterAttribute))
                {
                    Claim claims = context.HttpContext.User.Claims.FirstOrDefault(m => m.Type == nameof(Menu.Permission));
                    //如果没有权限声明信息，则拒绝访问
                    if (claims == null)
                    {
                        context.Result = new ForbidResult();
                    }

                    string[] permissions = claims.Value.Split(",");

                    if (!permission.Any(x => permissions.Contains(x)))
                    {
                        context.Result = new ForbidResult();
                    }
                }

                #region 弃用版本，改用权限标识判断
                /*
                IServiceProvider serviceProvider = context.HttpContext.RequestServices;
                var menuRepository = serviceProvider.GetService<IRepository<Menu>>();
                var roleMenuRepository = serviceProvider.GetService<IRepository<RoleMenu>>();
                var roleRepository = serviceProvider.GetService<IRepository<Role>>();
                string AttributeRouteInfo = "/" + context.ActionDescriptor.AttributeRouteInfo.Template;

                //http请求方法
                var HttpMethod = context.HttpContext.Request.Method;

                var RoleCode = (from menu in await menuRepository.GetQueryableAsync()
                                join rolemenu in await roleMenuRepository.GetQueryableAsync()
                                on menu.Id equals rolemenu.MenuId
                                join role in await roleRepository.GetQueryableAsync()
                                on rolemenu.RoleId equals role.Id
                                where menu.ApiPath == AttributeRouteInfo && menu.HttpMethod == HttpMethod
                                select role.RoleCode).ToList();

                if (RoleCode.Count <= 0)
                {
                    context.Result = new StatusCodeResult((int)HttpStatusCode.Forbidden);
                }

                string UserName = context.HttpContext.User.Identity.Name;
                IEnumerable<Claim> claims = context.HttpContext.User.Claims;

                string[] roleid = claims.First(m => m.Type == ClaimTypes.Role).Value.Split(',');

                if (!roleid.Any(RoleCode.Contains))
                {
                    context.Result = new StatusCodeResult((int)HttpStatusCode.Forbidden);
                }
                */
                #endregion
            }
        }
    }
}
